﻿// owner 蒋家伟

#pragma once
#include "IPrefixTree.h"

namespace jsdk
{
    class PrefixTree;
    class PrefixTreeNode
    {
        using ChildrenNodes = std::unordered_map<wchar_t, OwnerPtr<PrefixTreeNode>>;
    public:
        static OwnerPtr<PrefixTreeNode> create(wchar_t wchar);
        wchar_t getchar() const { return m_char; }
        uint32_t getPassCount() const { return m_passCount; }
        void addPasscount() { m_passCount++; }
        void subtractPasscount();
        void setisEnd(bool isend) { m_isEnd = isend; };
        bool isEnd() const { return m_isEnd; }
        PrefixTreeNode* getParent() const { return m_pParentNode; }
        void setParent(PrefixTreeNode* pParentNode) { m_pParentNode = pParentNode; }
        PrefixTreeNode* findfw(wchar_t wchar);
        const PrefixTreeNode* find(wchar_t wchar) const;
        bool addChildrenNode(OwnerPtr<PrefixTreeNode> opPrefixTreeNode);
        // 获取从此节点开始往下(不包含此节点的完整字符串)
        std::wstring getString() const;
        size_t getChildrenNodeSize() const { return m_childrenNodes.size(); }
        const ChildrenNodes& getChildrenNodes() const { return m_childrenNodes; }
    private:
        friend class PrefixTree;
        PrefixTreeNode(wchar_t wchar);
        wchar_t m_char = L'\0';                             // 当前节点所拥有的字符
        uint32_t m_passCount = 0;                           // 通过当前节点的次数
        bool m_isEnd = false;                               // 是否以当前节点结束
        PrefixTreeNode* m_pParentNode = nullptr;            // 父节点指针
        ChildrenNodes m_childrenNodes;                      // 子节点对象
    };

    class PrefixTree : public IPrefixTree
    {
    public:
        static OwnerPtr<PrefixTree> create();
    private:
        // 获取到此节点的字符串
        static std::wstring getPrefixString(const PrefixTreeNode* pPrefixTreeNode);
        // 获取包含此节点的完整字符串，结果不唯一
        static std::wstring getPrefixString2(const PrefixTreeNode* pPrefixTreeNode);
        virtual bool addPrefix(const std::wstring& prefixStr, std::wstring& errorMsg) override;
        virtual std::vector<std::pair<uint32_t, uint32_t>> match(const std::wstring& matchStr) const override;
        virtual void swap(OwnerPtr<IPrefixTree>& opPrefixTree) override;
        virtual uint32_t getPrefixCount() const override;
        virtual std::vector<std::wstring> getPrefixStr() const override;

    private:
        PrefixTree();
        OwnerPtr<PrefixTreeNode> m_opRootNode;
    };
}